// C source file with the function definitions to handle CP932 characters

// check_cp932_int() function
byte check_cp932_int(cp932_int ch)
{
  // if ch is valid it will return the character size in bytes, otherwise returns 0
  if ((ch >= MIN_ASCII_INT && ch <= MAX_ASCII_INT)
      || (ch >= CP932_UMAP_TB1_START && ch <= CP932_UMAP_TB1_END)) // table 1
    return 1;
  else if (ch >= CP932_UMAP_TB2_START && ch <= CP932_UMAP_TB2_END) /* table 2 */ {
    if (CP932_UMAP_TB2[ch - CP932_UMAP_TB2_START] != 0)
      goto size_2;
  }
  else if (ch >= CP932_UMAP_TB3_START && ch <= CP932_UMAP_TB3_END) /* table 3 */ {
    if (CP932_UMAP_TB3[ch - CP932_UMAP_TB3_START] != 0)
      goto size_2;
  }
  else if (ch >= CP932_UMAP_TB4_START && ch <= CP932_UMAP_TB4_END) /* table 4 */ {
    if (CP932_UMAP_TB4[ch - CP932_UMAP_TB4_START] != 0)
      goto size_2;
  }
  else if (ch >= CP932_UMAP_TB5_START && ch <= CP932_UMAP_TB5_END) /* table 5 */ {
    if (CP932_UMAP_TB5[ch - CP932_UMAP_TB5_START] != 0)
      goto size_2;
  }
  else if (ch >= CP932_UMAP_TB6_START && ch <= CP932_UMAP_TB6_END) /* table 6 */ {
    if (CP932_UMAP_TB6[ch - CP932_UMAP_TB6_START] != 0)
      goto size_2;
  }
  else if (ch >= CP932_UMAP_TB7_START && ch <= CP932_UMAP_TB7_END) /* table 7 */ {
    if (CP932_UMAP_TB7[ch - CP932_UMAP_TB7_START] != 0)
      goto size_2;
  }
  // character is nowhere to be found
  // or it is invalid
  return 0;
  size_2:
  return 2;
}

// check_enc_cp932() function
byte check_enc_cp932(void * src, umax ssize)
{
  // check character against check_cp932_int()
  // but first check the function parameters
  if (src == NULL || ssize == 0)
    return 0;
  
  // 1 byte check
  cp932_int ch = (cp932_int) ((byte *) src)[0];
  if (check_cp932_int(ch) == 1)
    return 1;
  // else, check if the character is 2 bytes long
  ch = 0; // reset ch
  cp_mem_bytes(src, 2, (byte *) &ch + sizeof(cp932_int) - 2);
  if (SYS_ENDIAN == LITTLE)
    reverse_array(&ch, sizeof(cp932_int), 1);
  return check_cp932_int(ch);
}

// get_cp932_int() function
cp932_int get_cp932_int(void * src, umax ssize)
{
  // check if the character in src is valid
  byte ch_size = check_enc_cp932(src, ssize);
  if (ch_size == 0)
    return INV_CP932_INT;
  
  // else return the character
  cp932_int ch = 0;
  cp_mem_bytes(src, ch_size, (byte *) &ch + sizeof(cp932_int) - ch_size);
  if (SYS_ENDIAN == LITTLE)
    reverse_array(&ch, sizeof(cp932_int), 1);
  return ch;
}

// write_enc_cp932() function
void * write_enc_cp932(cp932_int ch, void * dest, umax dsize)
{
  // check the function parameters
  byte ch_size = check_cp932_int(ch);
  if (dsize < ch_size || dest == NULL || dsize == 0)
    return NULL;
  
  // else write it lmao
  if (SYS_ENDIAN == LITTLE)
    reverse_array(&ch, sizeof(cp932_int), 1);
  if (dsize >= ch_size)
    cp_mem_bytes((byte *) &ch + sizeof(cp932_int) - ch_size, ch_size, dest);
  return (byte *) dest + ch_size;
}

// print_cp932_int() function
byte print_cp932_int(cp932_int ch)
{
  // invalid character
  byte rtn = check_cp932_int(ch);
  if (rtn == 0)
    printf(INV_CP932_INT_STR);
  else if (ch < 0x100)
    printf("%02llX", ch);
  else
    printf("%04llX", ch);
  return rtn;
}

// print_enc_cp932() function
byte print_enc_cp932(void * src, umax ssize)
{
  // invalid character
  byte rtn = check_enc_cp932(src, ssize);
  if (rtn == 0)
    printf(INV_ENC_CP932_STR);
  else // print the encoded bytes
    for (byte i = 0; i < rtn; i++)
      printf("%02X", ((byte *) src + i)[0]);
  return rtn;
}

// check_cp932_as_unicd() function
byte check_cp932_as_unicd(cp932_int ch)
{
  // all cp932_int characters are unicode compatible
  return check_cp932_int(ch);
}

// check_unicd_as_cp932() fnction
bool check_unicd_as_cp932(unicd_int ch)
{
  // check if the unicode character is ASCII
  // otherwise search in the CP932_UMAP_TB tables for it  
  if (ch >= MIN_ASCII_INT && ch <= MAX_ASCII_INT)
    goto valid;
  
  // otherwise search in the CP932_UMAP_TB tables for it  
  if (search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB1, CP932_UMAP_TB1_SIZE,
      unicd_int_equal) != NULL) goto valid; // table 1
  if (search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB2, CP932_UMAP_TB2_SIZE,
      unicd_int_equal) != NULL) goto valid; // table 2
  if (search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB3, CP932_UMAP_TB3_SIZE,
      unicd_int_equal) != NULL) goto valid; // table 3
  if (search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB4, CP932_UMAP_TB4_SIZE,
      unicd_int_equal) != NULL) goto valid; // table 4
  if (search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB5, CP932_UMAP_TB5_SIZE,
      unicd_int_equal) != NULL) goto valid; // table 5
  if (search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB6, CP932_UMAP_TB6_SIZE,
      unicd_int_equal) != NULL) goto valid; // table 6
  if (search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB7, CP932_UMAP_TB7_SIZE,
      unicd_int_equal) != NULL) goto valid; // table 7
  
  // invalid conversion
  return 0;
  valid:
  return 1;
}

// get_cp932_as_unicd() function
unicd_int get_cp932_as_unicd(cp932_int ch)
{
  // check the character
  if (check_cp932_as_unicd(ch) == 0)
    return INV_UNICD_INT;
  
  // else return the converted character
  if (ch >= MIN_ASCII_INT && ch <= MAX_ASCII_INT)
    return (unicd_int) ch; // ASCII
  if (ch >= CP932_UMAP_TB1_START && ch <= CP932_UMAP_TB1_END)
    return CP932_UMAP_TB1[ch - CP932_UMAP_TB1_START]; // table 1
  if (ch >= CP932_UMAP_TB2_START && ch <= CP932_UMAP_TB2_END)
    return CP932_UMAP_TB2[ch - CP932_UMAP_TB2_START]; // table 2
  if (ch >= CP932_UMAP_TB3_START && ch <= CP932_UMAP_TB3_END)
    return CP932_UMAP_TB3[ch - CP932_UMAP_TB3_START]; // table 3
  if (ch >= CP932_UMAP_TB4_START && ch <= CP932_UMAP_TB4_END)
    return CP932_UMAP_TB4[ch - CP932_UMAP_TB4_START]; // table 4
  if (ch >= CP932_UMAP_TB5_START && ch <= CP932_UMAP_TB5_END)
    return CP932_UMAP_TB5[ch - CP932_UMAP_TB5_START]; // table 5
  if (ch >= CP932_UMAP_TB6_START && ch <= CP932_UMAP_TB6_END)
    return CP932_UMAP_TB6[ch - CP932_UMAP_TB6_START]; // table 6
  return CP932_UMAP_TB7[ch - CP932_UMAP_TB7_START]; // table 7
}

// get_unicd_as_cp932() function
cp932_int get_unicd_as_cp932(unicd_int ch)
{
  // check the character
  if (check_unicd_as_cp932(ch) == 0)
    return INV_CP932_INT;
  
  // else return the converted character
  if (ch >= MIN_ASCII_INT && ch <= MAX_ASCII_INT)
    return (cp932_int) ch; // ASCII
  
  // otherwise check in the CP932_UMAP tables
  unicd_int * ptr = NULL;
  ptr = search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB1, CP932_UMAP_TB1_SIZE, unicd_int_equal);
  if (ptr != NULL)
    return (cp932_int) (ptr - &CP932_UMAP_TB1[0]) + CP932_UMAP_TB1_START; // table 1
  ptr = search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB2, CP932_UMAP_TB2_SIZE, unicd_int_equal);
  if (ptr != NULL)
    return (cp932_int) (ptr - &CP932_UMAP_TB2[0]) + CP932_UMAP_TB2_START; // table 2
  ptr = search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB3, CP932_UMAP_TB3_SIZE, unicd_int_equal);
  if (ptr != NULL)
    return (cp932_int) (ptr - &CP932_UMAP_TB3[0]) + CP932_UMAP_TB3_START; // table 3
  ptr = search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB4, CP932_UMAP_TB4_SIZE, unicd_int_equal);
  if (ptr != NULL)
    return (cp932_int) (ptr - &CP932_UMAP_TB4[0]) + CP932_UMAP_TB4_START; // table 4
  ptr = search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB5, CP932_UMAP_TB5_SIZE, unicd_int_equal);
  if (ptr != NULL)
    return (cp932_int) (ptr - &CP932_UMAP_TB5[0]) + CP932_UMAP_TB5_START; // table 5
  ptr = search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB6, CP932_UMAP_TB6_SIZE, unicd_int_equal);
  if (ptr != NULL)
    return (cp932_int) (ptr - &CP932_UMAP_TB6[0]) + CP932_UMAP_TB6_START; // table 6
  ptr = search_for_arr_elem(&ch, sizeof(unicd_int), CP932_UMAP_TB7, CP932_UMAP_TB7_SIZE, unicd_int_equal);
  return (cp932_int) (ptr - &CP932_UMAP_TB7[0]) + CP932_UMAP_TB7_START; // table 7
}
